﻿#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <iostream>
#include <math.h>
#include <corecrt_wstdio.h>
#include "../chapter12/EasyXPng.h"

#pragma comment(lib,"Winmm.lib")

using namespace std;

#define WIDTH 560
#define HEIGHT 800
#define	MAX_BULLET_NUM 200

void startup();
void show();
void update_without_input();
void update_with_input();
void sleep(DWORD ms);
void play_music_once(TCHAR file_name[80]);

class Rocket
{
public:
	IMAGE im_rocket;
	IMAGE im_blow_up;
	float x;
	float y;
	float width;
	float height;
	int live_second;
	int life;

	void draw()
	{
		for (int i = 0; i < life; i++)
		{
			putimagePng(i * width * 0.9, 0, &im_rocket);
		}

		TCHAR text[20];
		setbkmode(TRANSPARENT);
		swprintf_s(text, _T("%d秒"), live_second);
		settextstyle(40, 0, _T("黑体"));
		outtextxy(WIDTH * 0.85, 20, text);

		if (life > 0)
		{
			putimagePng(x - width / 2, y - height / 2, &im_rocket);
		}
		else
		{
			putimagePng(x - width / 2, y - height / 2, &im_blow_up);
		}
	}


	void update(float address_x, float address_y)
	{
		x = address_x;
		y = address_y;
	}


	void update_when_life_lost()
	{
		play_music_once(_T("explode.mp3"));
		life--;
	}
};

class Bullet
{
public:
	IMAGE im_bullet;
	float x;
	float y;
	float speed_x;
	float speed_y;
	float radius;

	void draw()
	{
		putimagePng(x - radius, y - radius, &im_bullet);
	}


	void update()
	{
		x += speed_x;
		y += speed_y;
		if (x <= 0 || x >= WIDTH)
		{
			speed_x = -speed_x;
		}
		if (y <= 0 || y >= HEIGHT)
		{
			speed_y = -speed_y;
		}
	}


	int collide_rocket(Rocket rocket)
	{
		float distance_x = abs(rocket.x - x);
		float distance_y = abs(rocket.y - y);
		if (distance_x < rocket.width / 2 && distance_y < rocket.height / 2)
		{
			return 1;
		}
		else
		{
			return 0;
		}
	}
};

class UFO : public Bullet
{
public:
	void update_velfor_targe(Rocket target_rocket)
	{
		float scalar = 1 * rand() / double(RAND_MAX) + 1;
		if (target_rocket.x > x)
			speed_x = scalar;
		else if (target_rocket.x < x)
			speed_x = -scalar;
		if (target_rocket.y > y)
			speed_y = scalar;
		else if (target_rocket.y < y)
			speed_y = -scalar;
	}
};

IMAGE im_bk;
IMAGE im_bullet;
IMAGE im_rocket;
IMAGE im_UFO;
IMAGE im_blow_up;
Bullet bullet[MAX_BULLET_NUM];
Rocket rocket;
UFO ufo;
int bullet_num = 0;

int main()
{
	startup();
	while (!(_kbhit() && _getch() == 'q'))
	{
		show();
		update_without_input();
		update_with_input();
	}

	return 0;
}


void startup()
{
	mciSendString(_T("open game_music.mp3 alias bkmusic"), NULL, 0, NULL);
	mciSendString(_T("play bkmusic repeat"), NULL, 0, NULL);

	srand(time(0));
	loadimage(&im_bk, _T("background.png"));
	loadimage(&im_bullet, _T("bullet.png"));
	loadimage(&im_rocket, _T("rocket.png"));
	loadimage(&im_blow_up, _T("blowup.png"));
	loadimage(&im_UFO, _T("ufo.png"));

	rocket.im_rocket = im_rocket;
	rocket.im_blow_up = im_blow_up;
	rocket.width = im_rocket.getwidth();
	rocket.height = im_rocket.getheight();
	rocket.life = 5;

	ufo.x = WIDTH / 2;
	ufo.y = 10;
	ufo.im_bullet = im_UFO;
	ufo.radius = im_UFO.getwidth() / 2;
	ufo.update_velfor_targe(rocket);

	initgraph(WIDTH, HEIGHT);

	BeginBatchDraw();
}


void show()
{
	putimage(0, 0, &im_bk);
	for (int i = 0; i < bullet_num; i++)
	{
		bullet[i].draw();
	}

	rocket.draw();
	ufo.draw();

	FlushBatchDraw();
	Sleep(10);
}


void update_without_input()
{
	if (rocket.life <= 0)
	{
		return;
	}

	static int last_second = 0;
	static int now_second = 0;
	static clock_t start = clock();
	clock_t now = clock();

	now_second = (int(now - start) / CLOCKS_PER_SEC);
	rocket.live_second = now_second;

	if (now_second == last_second + 1)
	{
		ufo.update_velfor_targe(rocket);
	}

	if (now_second == last_second + 2)
	{
		last_second = now_second;

		if (bullet_num < MAX_BULLET_NUM)
		{
			bullet[bullet_num].x = WIDTH / 2;
			bullet[bullet_num].y = 10;

			float angle = (rand() / double(RAND_MAX) - 0.5) * 0.9 * PI;
			float scalar = 2 * rand() / double(RAND_MAX) + 2;

			bullet[bullet_num].speed_x = scalar * sin(angle);
			bullet[bullet_num].speed_y = scalar * cos(angle);
			bullet[bullet_num].im_bullet = im_bullet;
			bullet[bullet_num].radius = im_bullet.getwidth() / 2;
		}
		bullet_num++;
	}

	for (int i = 0; i < bullet_num; i++)
	{
		bullet[i].update();

		if (bullet[i].collide_rocket(rocket))
		{
			rocket.update_when_life_lost();
			bullet[i].x = 5;
			bullet[i].y = 5;

			break;
		}
	}

	ufo.update();

	if (ufo.collide_rocket(rocket))
	{
		rocket.update_when_life_lost();
		ufo.x = 5;
		ufo.y = 5;
	}
}


void update_with_input()
{
	if (rocket.life <= 0)
	{
		return;
	}

	MOUSEMSG m;
	while (MouseHit())
	{
		m = GetMouseMsg();
		if (m.uMsg == WM_MOUSEMOVE)
		{
			rocket.update(m.x, m.y);
		}
	}
}


void sleep(DWORD ms)
{
	static DWORD old_time = GetTickCount();
	while (GetTickCount() - old_time < ms)
	{
		Sleep(1);
	}
	old_time = GetTickCount();
}


void play_music_once(TCHAR file_name[80])
{
	TCHAR string_1[50];
	swprintf_s(string_1, _T("open %s alias tmpmusic"), file_name);
	mciSendString(_T("close tmpmusic"), NULL, 0, NULL);
	mciSendString(string_1, NULL, 0, NULL);
	mciSendString(_T("play tmpmusic"), NULL, 0, NULL);
}